/**
 * 
 * 尽量为元素实现转移构造和转移赋值函数，
 * 在加入容器的时候使用 std::move() 来“转移”，减少元素复制的成本
 * 
 * 可以使用 C++11 为容器新增加的 emplace 操作函数，它可以“就地”构造元素，
 * 免去了构造后再拷贝、转移的成本，不但高效，而且用起来也很方便
 */

#include <vector>
#include <iostream>
#include <memory>
class TestClass
{
private:
    std::string name ="default";
public:
    TestClass(std::string name):name(name){};
    TestClass();
    ~TestClass();
    TestClass(const TestClass &);
    TestClass(TestClass &&);
};

TestClass::TestClass(/* args */)
{
}

TestClass::~TestClass()
{
}
TestClass::TestClass(const TestClass & tmp)
{
    std::cout <<tmp.name<<" copy" << std::endl;
}
TestClass::TestClass(TestClass && tmp)
{
    std::cout <<tmp.name<<" move" << std::endl;
}
class TestClassAnother{
public:
    TestClassAnother(){}
    ~TestClassAnother(){}

    //vector 通常保证强异常安全性，如果元素类型没有提供一个保证不抛异常的移动构造函数，vector 通常会使用拷贝构造函数。
    //因此，对于拷贝代价较高的自定义元素类型，我们应当定义移动构造函数，并标其为 noexcept，
    //或只在容器中放置对象的智能指针
    TestClassAnother(TestClassAnother && tmp) noexcept      //  noexcept
    {
        std::cout <<"move" << std::endl;
    }
    TestClassAnother(const TestClassAnother & tmp)
    {
        std::cout <<"copy" << std::endl;
    }
private:
    std::shared_ptr<char> m_data;
};

 int main()
{
    TestClass AAA("AAA");
    TestClass tc1("BBB");
    TestClass tc2("CCC");
    TestClass tc3("DDD");

    TestClass tc4 = std::move(AAA);
    std::cout<<"****-----------------------"<<std::endl;

    std::vector<TestClass> vec(10);
    std::cout<<"-----------------------"<<std::endl;
    vec.push_back(std::move(AAA));
    std::cout<<"-----------------------"<<std::endl;
    vec.push_back(tc1);
    std::cout<<"-----------------------"<<std::endl;
    vec.emplace_back(tc2);
    std::cout<<"-----------------------"<<std::endl;
    vec.emplace_back(std::move(tc3));

    std::cout<<"-----------------------******************************"<<std::endl;
    TestClassAnother tca;
    TestClassAnother tca1;
    std::vector<TestClassAnother> veca;
    veca.emplace_back(tca);
    std::cout<<"-----------------------******************************"<<std::endl;
    veca.emplace_back(std::move(tca1));
}